package com.estar.integaration.Controller.paymentPlanController;

import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.estar.integaration.Reader.DueReceiptDetailReader;
import com.estar.integaration.Reader.PurchaseOrderDetailReader;
import com.estar.integaration.Reader.ReceiptComeLedgerReader;
import com.estar.integaration.Reader.SupplierAccountPeriodReader;
import com.estar.integaration.Service.paymentPlanService.*;
import com.estar.integaration.Util.DateParseUtil;
import com.estar.integaration.Util.FileUtil;
import com.estar.integaration.Util.StringUtil;
import com.estar.integaration.Util.Util;
import com.estar.integaration.entity.NoSQL.Res;
import com.estar.integaration.entity.paymentPlanEntity.*;
import com.estar.integaration.strategy.PaymentPlanContext;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.Timestamp;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Author: YJL
 * Date: 2022/2/18 13:39
 **/

@RestController
@RequestMapping("/payment-plan")
public class PaymentPlanAnalyseController {

  @Value("${spring.profiles.active}")
  private String mEnvironment;


  @Autowired
  private IDueReceiptDetailService dueReceiptDetailService;

  @Autowired
  private IPurchaseOrderDetailService purchaseOrderDetailService;

  @Autowired
  private IReceiptComeLedgerService receiptComeLedgerService;

  @Autowired
  private ISupplierAccountPeriodService supplierAccountPeriodService;

  @Autowired
  private ISupplierAccountMultipleSituationService supplierAccountMultipleSituationService;

  @Autowired
  private  IDontParseSupplierService dontParseSupplierService;

  @Autowired
  private IPaymentPlanHistoryService paymentPlanHistoryService;

  List<PurchaseOrderDetail> purchaseOrderDetailList = null;
  List<DueReceiptDetail> dueReceiptDetailList = null;
  List<ReceiptComeLedger> receiptComeLedgerList = null;
  List<SupplierAccountPeriod> supplierAccountPeriodList = null;
  List<PurchaseOrderDetail> returnList = null;

  List<String> groupList = new ArrayList<>();

  //获取全部文件,读取全部本地文件,不走数据库
  @GetMapping("/get-all-POD")
  public Res getAllRes(){
//     purchaseOrderDetailList = purchaseOrderDetailService.getAllPurchaseOrderDetail();
    /**
     dueReceiptDetailList = dueReceiptDetailService.getAllDueReceiptDetail();
     receiptComeLedgerList = receiptComeLedgerService.getAllReceiptComeLedger();
     supplierAccountPeriodList = supplierAccountPeriodService.getAllSupplierAccountPeriod();**/
     String dueFolderAddress = mEnvironment.equals("dev") ? "D:\\SCM_file\\paymentPlan\\dueReceiptDetail" : "/root/excel/paymentPlan/dueReceiptDetail";;
     String purchaseFolderAddress = mEnvironment.equals("dev") ? "D:\\SCM_file\\paymentPlan\\purchaseOrderDetail" : "/root/excel/paymentPlan/purchaseOrderDetail";;
     String receiptFolderAddress = mEnvironment.equals("dev") ? "D:\\SCM_file\\paymentPlan\\receiptComeLedger" : "/root/excel/paymentPlan/receiptComeLedger";;
//     String supplierFolderAddress = mEnvironment.equals("dev") ? "D:\\SCM_file\\paymentPlan\\supplierAccountPeriod" : "/root/excel/paymentPlan/supplierAccountPeriod";
     dueReceiptDetailList = readDue(dueFolderAddress);
     purchaseOrderDetailList = readPurchase(purchaseFolderAddress);
     //后勤组现在正常解析
//     purchaseOrderDetailList = purchaseOrderDetailList.stream().filter( p-> !p.getPurchaseGroup().equals("采购后勤组")).collect(Collectors.toList());
     receiptComeLedgerList = readReceipt(receiptFolderAddress);
     supplierAccountPeriodList = supplierAccountPeriodService.getAllSupplierAccountPeriod();
     return new Res("20000",new Gson().toJson(purchaseOrderDetailList));
  }



  @PostMapping("/analyse")
  public Res analyse(@RequestBody JSONObject jsonObject){//解析出结果
    List<SupplierAccountMultipleSituation> supplierAccountMultipleSituationList = new ArrayList<>();
    supplierAccountMultipleSituationList = supplierAccountMultipleSituationService.getAllSPAMS();
    //把全部的多情况List
    JSONArray jsonArray = jsonObject.getJSONArray("groups");
    List<String> groupList = JSONObject.parseArray(jsonArray.toJSONString(),String.class);
    List<PurchaseOrderDetail> newPurchaseOrderDetail = purchaseOrderDetailList.stream().filter(p-> groupList.contains(p.getPurchaseGroup())).collect(Collectors.toList());
    PaymentPlanContext paymentPlanContext = new PaymentPlanContext(newPurchaseOrderDetail,dueReceiptDetailList,receiptComeLedgerList,supplierAccountPeriodList,supplierAccountMultipleSituationList);
    returnList = paymentPlanContext.execute();

    List<PurchaseOrderDetail> errorPODList = returnList.stream().filter(p->p.getExpectPayDate().equals("ERR")).collect(Collectors.toList());
    returnList = returnList.stream().filter(p -> !p.getExpectPayDate().equals("ERR")).collect(Collectors.toList());//去掉错误的
    //处理错误List
    errorPODList = paymentPlanContext.twiceLayerAnalyse(errorPODList);
    returnList.addAll(errorPODList);

    //去掉发票到票台账中没有"开票日期"
//    returnList = returnList.stream().filter(p -> p.getExpectPayDate() != null && !p.getExpectPayDate().equals("无付款计划")).collect(Collectors.toList());
    List<ExportPurchaseOrderDetail> exportPurchaseOrderDetailList = solvePurchaseList2EpodList(returnList);
    return new Res("20000",new Gson().toJson(exportPurchaseOrderDetailList));
  }


  @GetMapping("/groups")
  public Res getGroups(){//获得所有的组
    groupList = getGroupList(purchaseOrderDetailList);
    return new Res("20000",new Gson().toJson(groupList));
  }

  @GetMapping("/summary")
  public Res summary(){
//    Optional<Double> summary = returnList.stream().map(PurchaseOrderDetail::getNeedPayAmount,).reduce(Double::sum);
    Double summaryMoney = 0.0d;
    for(PurchaseOrderDetail p : returnList){
      System.out.println(p.getNeedPayAmount());
      System.out.println(returnList.indexOf(p));
      if(p.getNeedPayAmount() < 0)
        continue;
      summaryMoney += p.getNeedPayAmount();
    }
    String returnSummary = String.format("%.3f",summaryMoney);
    return new Res("20000",returnSummary);
  }


  @GetMapping("/downloadExcel")
  @ResponseBody
  public void downLoadExcel(HttpServletResponse response){

//    List<ExportPurchaseOrderDetail> exportPurchaseOrderDetailList = cloneList(returnList);
//    //等于0的不需要
//    exportPurchaseOrderDetailList = exportPurchaseOrderDetailList.stream().filter(p-> ! (Math.abs(p.getNeedPayAmount()) < 0.000001)).collect(Collectors.toList());
//    List<String> dontParseSuppliers = new ArrayList<>();
//    dontParseSupplierService.getAllDontParseSupplier().forEach(dps -> dontParseSuppliers.add(dps.getSupplierName()));
//    exportPurchaseOrderDetailList = exportPurchaseOrderDetailList.stream().filter(p ->
//        {
//          if(dontParseSuppliers.contains(p.getSupplierName())){ //全部不解析
//            return false;
//          }else if(!dontParseSuppliers.contains(p.getSupplierName())){
//            return true;
//          }else {
//            return true;
//          }
//        }
//    ).collect(Collectors.toList());
    List<ExportPurchaseOrderDetail> exportPurchaseOrderDetailList = solvePurchaseList2EpodList(returnList);
    writeExcel(response,exportPurchaseOrderDetailList,"付款计划");
  }

  /**
   * 按照供应商
   * @return
   */
  @PostMapping("/filter_supplierName")
  public Res filterBySupplierName(@RequestBody JSONObject jsonObject){
    String supplierName = jsonObject.getString("supName");
    returnList = returnList.stream().filter(p-> p.getSupplierName().contains(supplierName)).collect(Collectors.toList());
    returnList = sortByDateAndSplitNoTime(returnList);
    return new Res("20000",new Gson().toJson(returnList));
  }

  @PostMapping("/filter_by_date")
  public Res filterByDate(@RequestBody JSONObject jsonObject){
    JSONArray date = jsonObject.getJSONArray("fil_date");
    List<String> dateList = JSONArray.parseArray(date.toJSONString(),String.class);
    String startDate = dateList.get(0);
    String lastDate = dateList.get(1);
    returnList = returnList.stream().filter(p->
        {
          if(!p.getExpectPayDate().contains("/"))
            return false;
         if((DateParseUtil.compareDate(p.getExpectPayDate(),startDate).equals(1) || DateParseUtil.compareDate(p.getExpectPayDate(),startDate).equals(0))
          && (DateParseUtil.compareDate(p.getExpectPayDate(),lastDate).equals(-1) || DateParseUtil.compareDate(p.getExpectPayDate(),lastDate).equals(0))
         ) {//p的date<start p.data>last
           return true;
         }else
           return false;
        }
        ).sorted(Comparator.comparing(PurchaseOrderDetail::getExpectPayDate,Comparator.nullsLast(String::compareTo)))
        .collect(Collectors.toList()); // 本时间 > startTime并且 < lastDate
//      List<PurchaseOrderDetail> noEpDateList = returnList.stream().filter(p-> !p.getExpectPayDate().contains("/")).collect(Collectors.toList());
//      returnList = returnList.stream().filter(p-> p.getExpectPayDate().contains("/")).collect(Collectors.toList());
//      DateParseUtil.ListSort(returnList);
//      returnList.addAll(noEpDateList);
    returnList = sortByDateAndSplitNoTime(returnList);
    return new Res("20000",new Gson().toJson(returnList));
  }




  @PostMapping("/getListByType")
  public Res getThisTypeList(@RequestBody JSONObject jsonObject){
    String type = jsonObject.getString("history_type");
    List<PaymentPlanHistory> paymentPlanHistoryList = paymentPlanHistoryService.getHistoryByType(type);
    DateParseUtil.sortPaymentHistory(paymentPlanHistoryList);
    return new Res("20000",new Gson().toJson(paymentPlanHistoryList));
  }



  @GetMapping("/sortByS")
  public Res sortBySupplier(){
    if(returnList == null)
      return null;
    returnList = returnList.stream().sorted(Comparator.comparing(PurchaseOrderDetail::getSupplierName,Comparator.nullsLast(String::compareTo))).collect(Collectors.toList());
    return new Res("20000",new Gson().toJson(returnList));
  }

  @GetMapping("/sortByD")
  public Res sortByDate(){

//    sortByDateM(returnList);
//    List<PurchaseOrderDetail> noEpDateList = returnList.stream().filter(p-> !p.getExpectPayDate().contains("/")).collect(Collectors.toList());
//    returnList = returnList.stream().filter(p-> p.getExpectPayDate().contains("/")).collect(Collectors.toList());
//    DateParseUtil.ListSort(returnList);
//    returnList.addAll(noEpDateList);

    return new Res("20000",new Gson().toJson(sortByDateAndSplitNoTime(returnList)));

  }

  /**
   * 把原purchaseOrderList进行去0，去掉不解析供应商操作。
   * @param purchaseOrderDetailList
   * @return
   */
  private List<ExportPurchaseOrderDetail> solvePurchaseList2EpodList (List<PurchaseOrderDetail> purchaseOrderDetailList){
    List<ExportPurchaseOrderDetail> exportPurchaseOrderDetailList = cloneList(purchaseOrderDetailList);
    //等于0的不需要
    exportPurchaseOrderDetailList = exportPurchaseOrderDetailList.stream().filter(p-> ! (Math.abs(p.getNeedPayAmount()) < 0.000001)).collect(Collectors.toList());
    List<String> dontParseSuppliers = new ArrayList<>();
    dontParseSupplierService.getAllDontParseSupplier().forEach(dps -> dontParseSuppliers.add(dps.getSupplierName()));
    exportPurchaseOrderDetailList = exportPurchaseOrderDetailList.stream().filter(p ->
        {
          if(dontParseSuppliers.contains(p.getSupplierName())){ //全部不解析
            return false;
          }else if(!dontParseSuppliers.contains(p.getSupplierName())){
            return true;
          }else {
            return true;
          }
        }
    ).collect(Collectors.toList());
    return exportPurchaseOrderDetailList;
  }

  /**
   * 把无日期的和有的拆开并且排序
   * @param returnList
   * @return
   */
  private List<PurchaseOrderDetail> sortByDateAndSplitNoTime(List<PurchaseOrderDetail> returnList){
    List<PurchaseOrderDetail> noEpDateList = returnList.stream().filter(p-> !p.getExpectPayDate().contains("/")).collect(Collectors.toList());
    returnList = returnList.stream().filter(p-> p.getExpectPayDate().contains("/")).collect(Collectors.toList());
    DateParseUtil.ListSort(returnList);
    returnList.addAll(noEpDateList);
    return returnList;
  }

  /**
   * 从List中找到所有的组
   * @return
   */
  private List<String> getGroupList(List<PurchaseOrderDetail> purchaseOrderDetailList){
    List<String> groupList = null;
    Set<String> groupSet = new HashSet<>();
    purchaseOrderDetailList.forEach(p-> {
      groupSet.add(p.getPurchaseGroup());
    });
    groupList = new ArrayList<>(groupSet);
    return groupList;
  }


  /**
   * EasyExcel导出Excel
   * @param response
   * @param list
   * @param fileName
   */
  private void writeExcel(HttpServletResponse response, List<ExportPurchaseOrderDetail> list,String fileName){
    OutputStream outputStream = getOutputStream(response,fileName);
    com.alibaba.excel.ExcelWriter excelWriter = EasyExcel.write(outputStream,ExportPurchaseOrderDetail.class).build();
    WriteSheet writeSheet = EasyExcel.writerSheet("sheet1").build();
    excelWriter.write(list,writeSheet);
    excelWriter.finish();
  }

  private List<ExportPurchaseOrderDetail> cloneList(List<PurchaseOrderDetail> list){
    List<ExportPurchaseOrderDetail> exportPurchaseOrderDetailList = new ArrayList<>();
    for(PurchaseOrderDetail p : list){
      if(p.getNeedPayAmount() == null){
//        System.out.println("needPayAmount为空" + p.getMaterialName());
        p.setNeedPayAmount(-9999999d);
//        continue;
      }
      ExportPurchaseOrderDetail exP = null;
      //特殊的，应付直接就是应付
      if(p.getIfSpecial() == null)
        System.out.println(p.getSupplierName());
      if(p.getIfSpecial()){
        exP = new ExportPurchaseOrderDetail(p.getSupplierName(),
            p.getOrderNumber(),
            p.getMaterialNumber(),
            p.getMaterialName(),
            p.getDrawingNo(),
            p.getSpec(),
            p.getBrand(),
            p.getPredeterminedNumber(),
            p.getPriceWithTax(),
            p.getPriceTaxGather(),
            p.getAmountDue(),
            p.getInventoryMoney(),
            p.getInventoryDate(),
            p.getTicketComeTime(),
            p.getExpectPayDate(),
            p.getPayAmount(),
            p.getNeedPayAmount(),
            p.getType(),
            p.getTaxPoint(),
            p.getNeedPayDate()
        );
      }else if(!p.getIfSpecial()){//正常的直接用应付-已付
        exP = new ExportPurchaseOrderDetail(p.getSupplierName(),
            p.getOrderNumber(),
            p.getMaterialNumber(),
            p.getMaterialName(),
            p.getDrawingNo(),
            p.getSpec(),
            p.getBrand(),
            p.getPredeterminedNumber(),
            p.getPriceWithTax(),
            p.getPriceTaxGather(),
            p.getAmountDue(),
            p.getInventoryMoney(),
            p.getInventoryDate(),
            p.getTicketComeTime(),
            p.getExpectPayDate(),
            p.getPayAmount(),
            p.getNeedPayAmount() - p.getPayAmount(),
            p.getType(),
            p.getTaxPoint(),
            p.getNeedPayDate()
        );
      }else {
        System.out.println(exP.getMaterialNumber() + "遗漏物料");
      }
      exportPurchaseOrderDetailList.add(exP);
    }
    return exportPurchaseOrderDetailList;
  }

  /**
   * 导出时生成OutputStream
   */
  private static OutputStream getOutputStream(HttpServletResponse response,String fileName) {
    //创建本地文件
    String filePath = fileName + ".xlsx";
    File file = new File(filePath);
    try { // 先设置 header 和 contentType。写在最后的原因是，避免报错时，响应 contentType 已经被修改了
      if (!file.exists() || file.isDirectory()) {
        file.createNewFile();
      }
      fileName = new String(filePath.getBytes(), "ISO-8859-1");
      response.setContentType("application/vnd.ms-excel;charset=utf-8");
      response.addHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
      return response.getOutputStream();
    } catch (IOException  e) {
      e.printStackTrace();
    }
    return null;
  }


  @PostMapping("/import-purchase-order-detail")
  @ResponseBody
  public Res importExcel(HttpServletRequest request) {
    String folderAddress = mEnvironment.equals("dev") ? "D:\\SCM_file\\paymentPlan\\purchaseOrderDetail" : "/root/excel/paymentPlan/purchaseOrderDetail";
//    String folderAddress = "/root/excel/inventoryFile/inventoryAge";
    //删除原文件夹全部文件
    Util.deleteAllFile(new File(folderAddress));
    //添加进去新文件
    MultipartHttpServletRequest params = (MultipartHttpServletRequest) request;
    List<MultipartFile> multipartFiles = params.getFiles("files");
    Vector<String> multipartFilePath = new Vector<>();//上传文件的地址
    for (MultipartFile file : multipartFiles) {
      //文件写入本地
      String address = Util.writePaymentFile2Local(file,folderAddress);
      multipartFilePath.add(address);
      insertHistory(file.getOriginalFilename());
    }
    List<PurchaseOrderDetail> list =  readPurchase(folderAddress);
    list.remove(list.size() -1 );
    purchaseOrderDetailList = list;//不记录进List
    return new Res("20000",new Gson().toJson(paymentPlanHistoryService.getHistoryByType("采购订单")));//上传成功

  }


  //插入采购订单执行明细历史
  private void insertHistory(String fileName){
    Timestamp timestamp = new Timestamp(System.currentTimeMillis());
    PaymentPlanHistory paymentPlanHistory = new PaymentPlanHistory(Util.getUUID(),fileName,timestamp,"采购订单");
    paymentPlanHistoryService.save(paymentPlanHistory);
  }

  /**
   * 读取采购订单执行明细
   * @param folderAddress
   * @return
   */
  private List<PurchaseOrderDetail> readPurchase(String folderAddress){
    List<String> fileList = FileUtil.getFilesinFolder(folderAddress);
    PurchaseOrderDetailReader purchaseOrderDetailReader = new PurchaseOrderDetailReader(fileList);
    List<PurchaseOrderDetail> list = purchaseOrderDetailReader.readPurchaseODR();
    return list;
  }

  /**
   * 读取应付帐单
   * @param folderAddress
   * @return
   */
  private List<DueReceiptDetail> readDue(String folderAddress){
    List<String> fileList = FileUtil.getFilesinFolder(folderAddress);
    DueReceiptDetailReader dueReceiptDetailReader = new DueReceiptDetailReader(fileList);
    List<DueReceiptDetail> dueReceiptDetailList = dueReceiptDetailReader.readDueRD();
    return dueReceiptDetailList;
  }

  /**
   * 读取发票到票台账
   * @param folderAddress
   * @return
   */
  private List<ReceiptComeLedger> readReceipt(String folderAddress){
    List<String> fileList = FileUtil.getFilesinFolder(folderAddress);
    ReceiptComeLedgerReader reader = new ReceiptComeLedgerReader(fileList);
    List<ReceiptComeLedger> list = reader.readReceiptComeLedger();
    return list;
  }

  /**
   * 读取供应商账期
   * @param folderAddress
   * @return
   */
  private List<SupplierAccountPeriod> readSupplier(String folderAddress){
    List fileList = FileUtil.getFilesinFolder(folderAddress);
    SupplierAccountPeriodReader reader = new SupplierAccountPeriodReader(fileList);
    List<SupplierAccountPeriod> list = reader.readDueSupplierAPR();
    return list;
  }

  /**
   * 设置税点
   * @param purchaseOrderDetailList
   */
  private List<PurchaseOrderDetail> setTaxPoint(List<PurchaseOrderDetail> purchaseOrderDetailList,Map<String,ReceiptComeLedger> receiptComeLedgerMap){
    for (PurchaseOrderDetail p : purchaseOrderDetailList){
      String orderNumber = p.getOrderNumber();//单据编号
      ReceiptComeLedger receiptComeLedger = null;
      if(receiptComeLedgerMap.containsKey(orderNumber)){
        receiptComeLedger = receiptComeLedgerMap.get(orderNumber);
        if(receiptComeLedger.getTaxPoint() != null //税点不为空 满足了
        ){
          if(!receiptComeLedger.getTaxPoint().equals(" ")//不是空
              && !receiptComeLedger.getTaxPoint().equals("")
          ){
            p.setTaxPoint(receiptComeLedger.getTaxPoint());
          }
        }
      }
    }
    return purchaseOrderDetailList;
  }




}
